package com.study.proxy;

import org.junit.jupiter.api.Test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.util.Arrays;

/**
 * @author: jzhou
 * @date: 2025/6/14-15:34
 * @version: 1.0
 * @description: juc-study
 */
public class ProxyTest {

    /**
     * 通过getProxyClass方法获取代理实例
     */
    @Test
    public void test() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Foo foo = new RealFoo();
        // 根据类加载器和接口数组获取代理类的Class对象
        Class<?> proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);

        // 通过Class对象的构造器创建一个实例（代理类的实例）
        Foo fooProxy = (Foo) proxyClass.getConstructor(InvocationHandler.class)
                .newInstance(new MyInvocationHandler(foo));

        // 调用 ping 方法，并输出返回值
        String value = fooProxy.ping("杨过");
        System.out.println(value);
    }

    /**
     * 通过这种方法是最简单的，也是推荐使用的，通过该方法可以直接获取代理对象。
     */
    @Test
    public void test2() {
        Foo foo = new RealFoo();
        Foo fooProxy = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class[]{Foo.class}, new MyInvocationHandler(foo));
        String value = fooProxy.ping("小龙女");
        System.out.println(value);
    }

    /**
     * 通过Lambda表达式简化实现
     */
    @Test
    public void test3() {
        Foo foo = new RealFoo();
        Foo fooProxy = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class[]{Foo.class},
                (proxy, method, args) -> {
                    System.out.println("proxy:" + proxy.getClass().getName());
                    System.out.println("method:" + method.getName());
                    System.out.println("args:" + Arrays.toString(args));
                    return method.invoke(foo, args);
                });
        System.out.println(fooProxy.ping("阿雕"));
    }
}
